package dnl.toolbox.lang;

import java.util.Collection;
import java.util.Iterator;
import java.util.Set;

import org.apache.commons.lang.ArrayUtils;

/**
 * @author Daniel
 */
public final class Args {

	public static void assertFalse(boolean b, String message) {
		if (b) {
			throw new IllegalArgumentException(message);	
		}
	}		
	
	public static void assertTrue(boolean b, String message) {
		if (!b) {
			throw new IllegalArgumentException(message);	
		}
	}	
	
	/**
	 * 
	 * @param aObject
	 */
	public static void assertNotNull(Object aObject) {
		if (aObject == null) {
			throw new IllegalArgumentException("null parameter.");
		}
	}

	public static void assertNotEmpty(Object[] array) {
		if (array.length == 0) {
			throw new IllegalArgumentException("Empty array.");
		}
	}

	public static void assertNull(Object aObject, String errMessage) {
		if (aObject != null) {
			throw new IllegalArgumentException(errMessage);
		}
	}

	/**
	 * Asserts that a given (argument) object has one of several possible
	 * values.
	 * 
	 * @param argName
	 *            the name of the argument.
	 * @param aObject
	 *            any object.
	 * @param possibleValues
	 *            the various valid values for <code>aObject</code>.
	 */
	public static void assertOneOf(String argName, Object aObject,
			Object[] possibleValues) {
		if (!ArrayUtils.contains(possibleValues, aObject)) {
			StringBuffer sb = new StringBuffer();
			for (int i = 0; i < possibleValues.length; i++) {
				sb.append(i);
				sb.append('.');
				sb.append(possibleValues.toString());
				sb.append('\n');
			}
			throw new IllegalArgumentException("Argument '" + argName
					+ "' must be one of:\n" + sb);
		}
	}

	/**
	 * Asserts that a given (argument) object has one of several possible
	 * values.
	 * 
	 * @param argName
	 *            the name of the argument.
	 * @param aObject
	 *            any object.
	 * @param possibleValues
	 *            the various valid values for <code>aObject</code>.
	 */
	public static void assertOneOf(String argName, Object aObject,
			Set<?> possibleValues) {
		if (!possibleValues.contains(aObject)) {
			StringBuffer sb = new StringBuffer();
			int i = 0;
			for (Iterator<?> iter = possibleValues.iterator(); iter.hasNext(); i++) {
				Object element = iter.next();
				sb.append(i);
				sb.append('.');
				sb.append(element.toString());
				sb.append('\n');
			}
			throw new IllegalArgumentException("Argument '" + argName
					+ "' must be one of:\n" + sb);
		}
	}

	/**
	 * Asserts that a and b are equal or that both are <code>null</code>.
	 * 
	 * @param a
	 *            first <code>Object</code>.
	 * @param b
	 *            second <code>Object</code>.
	 * @param message
	 *            a message that will be attached to any generated
	 *            <code>IllegalArgumentException</code>.
	 */
	public static void assertEquals(Object a, Object b, String message) {
		if (a == null) {
			if (b != null) {
				throw new IllegalArgumentException(message);
			}
		} else if (!a.equals(b)) {
			throw new IllegalArgumentException(message);
		}
	}

	/**
	 * Asserts that a and b are equal.
	 * 
	 * @param a
	 *            first <code>Object</code>.
	 * @param b
	 *            second <code>Object</code>.
	 * @param message
	 *            a message that will be attached to any generated
	 *            <code>IllegalArgumentException</code>.
	 */
	public static void assertEquals(int a, int b, String message) {
		if (a != b) {
			throw new IllegalArgumentException(message);
		}
	}

	/**
	 * Throw an <code>IllegalArgumentException</code> if <code>aText</code>
	 * does not satisfy.
	 * 
	 */
	public static void checkForContent(String aText) {
		if (!textHasContent(aText)) {
			throw new IllegalArgumentException("Text has no visible content");
		}
	}

	/**
	 * Throw an <code>IllegalArgumentException</code> if value is out of
	 * range.
	 * 
	 * @param aLow
	 *            is less than or equal to <code>aHigh</code>.
	 */
	public static void checkForRange(int aNumber, int aLow, int aHigh) {
		if (!isInRange(aNumber, aLow, aHigh)) {
			throw new IllegalArgumentException(aNumber + " not in range "
					+ aLow + ".." + aHigh);
		}
	}

	/**
	 * Throw an <code>IllegalArgumentException</code> only if
	 * <code>aCollection.isEmpty</code> returns <code>true</code>.
	 */
	public static void checkForEmpty(Collection<?> aCollection) {
		if (aCollection.isEmpty()) {
			throw new IllegalArgumentException("Collection is empty.");
		}
	}

	/**
	 * Return <code>true</code> only if <code>aText</code> is not null, and
	 * is not empty after trimming. (Trimming removes both leading/trailing
	 * whitespace and ASCII control characters.)
	 * 
	 * 
	 * @param aText
	 *            possibly-null.
	 */
	public static boolean textHasContent(String aText) {
		return (aText != null) && (aText.trim().length() > 0);
	}

	/**
	 * Return <code>true</code> only if <code>aNumber</code> is in the range
	 * <code>aLow..aHigh</code> (inclusive).
	 * 
	 * @param aLow
	 *            less than or equal to <code>aHigh</code>.
	 */
	static public boolean isInRange(int aNumber, int aLow, int aHigh) {
		if (aLow > aHigh) {
			throw new IllegalArgumentException("Low is greater than High.");
		}
		return (aLow <= aNumber && aNumber <= aHigh);
	}
}